export class InputManager {
  private _storedRawValue: string;

  constructor(private htmlInputElement: any) {}

  /**
   * 修改值并设置光标位置
   * @param newRawValue
   * @param oldLength
   * @param selectionStart
   */
  updateValueAndCursor(newRawValue: string, oldLength: number, selectionStart: number): void {
    this.rawValue = newRawValue;
    const newLength = newRawValue.length;
    selectionStart = selectionStart - (oldLength - newLength);
    this.setCursorAt(selectionStart);
  }

  /**
   * 设置光标位置
   * @param position
   */
  setCursorAt(position: number): void {
    if (this.htmlInputElement.setSelectionRange) {
      this.htmlInputElement.focus();
      this.htmlInputElement.setSelectionRange(position, position);
    } else if (this.htmlInputElement.createTextRange) {
      const textRange = this.htmlInputElement.createTextRange();
      textRange.collapse(true);
      textRange.moveEnd('character', position);
      textRange.moveStart('character', position);
      textRange.select();
    }
  }

  /**
   * 当前input的输入内容的起始与结束位置
   * @returns {{selectionStart: number, selectionEnd: number}}
   */
  get inputSelection(): any {
    let selectionStart = 0;
    let selectionEnd = 0;
    const el = this.htmlInputElement;

    // 如果是数字的话直接赋值
    if (typeof el.selectionStart === 'number' && typeof el.selectionEnd === 'number') {
      selectionStart = this.htmlInputElement.selectionStart;
      selectionEnd = this.htmlInputElement.selectionEnd;
    } else {
      // ie 浏览器获取开始与结束位置
      // @ts-ignore
      // 返回当前光标所在节点
      const range = document.getSelection().anchorNode;
      // 是否是当前input节点
      if (range && range.firstChild === this.htmlInputElement) {
        const lenght = this.htmlInputElement.value.length;
        const normalizedValue = this.htmlInputElement.value.replace(/\r\n/g, '\n');
        const startRange = this.htmlInputElement.createTextRange();
        const endRange = this.htmlInputElement.createTextRange();
        endRange.collapse(false);

        if (startRange.compareEndPoints('StartToEnd', endRange) > -1) {
          selectionStart = selectionEnd = lenght;
        } else {
          selectionStart = -startRange.moveStart('character', -lenght);
          selectionStart += normalizedValue.slice(0, selectionStart).split('\n').length - 1;

          if (startRange.compareEndPoints('EndToEnd', endRange) > -1) {
            selectionEnd = lenght;
          } else {
            selectionEnd = -startRange.moveEnd('character', -lenght);
            selectionEnd += normalizedValue.slice(0, selectionEnd).split('\n').length - 1;
          }
        }
      }
    }

    return {
      selectionStart: selectionStart,
      selectionEnd: selectionEnd,
    };
  }

  /**
   * 判断是否可以输入更多值
   * @returns {boolean}
   */
  get canInputMoreNumbers(): boolean {
    const haventReachedMaxLength = !(this.rawValue.length >= this.htmlInputElement.maxLength && this.htmlInputElement.maxLength >= 0);
    const selectionStart = this.inputSelection.selectionStart;
    const selectionEnd = this.inputSelection.selectionEnd;
    const haveNumberSelected =
      selectionStart !== selectionEnd && this.htmlInputElement.value.substring(selectionStart, selectionEnd).match(/\d/) ? true : false;
    const startWithZero = this.htmlInputElement.value.substring(0, 1) === '0';
    return haventReachedMaxLength || haveNumberSelected || startWithZero;
  }

  //===
  get rawValue(): string {
    return this.htmlInputElement && this.htmlInputElement.value;
  }

  set rawValue(value: string) {
    this._storedRawValue = value;

    if (this.htmlInputElement) {
      this.htmlInputElement.value = value;
    }
  }
}
